-
Notifications
You must be signed in to change notification settings - Fork 50
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable capture of RX features from RADE decoder #776
Conversation
Pinging @drowe67. Does this look like the feature you're looking for? |
@tmiw - I think so but there's quite a bit going on above ☝️, can you pls snip the irrelevant bits and make it clearer? I'm trying to see which I think I've sorted out that annoying warning in drowe67/radae#33. Looks like good progress 👍 - this could be very useful 🙂 |
I updated the description above. Hopefully that helps? |
@tmiw - yes that's looking better. A couple of suggestions:
Reminder to self - clean up spurious prints in RADE tools! 🙂 |
@tmiw - can the freedv-tx run in CLI mode?
where
These are just brain-storms atm, at some stage I'll formalise this with a test plan and we can get others involved (e.g. the August 2024 test team). |
When I tried converting
Not sure what's going on there.
Cool. 👍 Just did the following:
with plots below:
I don't think so but on Linux at least, you can use
The |
The plots looks good, no huge variation. Note the
I find it useful to plot the waveforms to get to the bottom of these sorts of bugs. I have Octave load_f32, load_raw functions to help, or Audacity can plot wave files. This worked for me (top two lines generate tx.wav, the rest is a reference receiver to check tx.wav):
These problems won't be hard to resolve if we really want to perform these experiments. You need to feed the same wavefile into the freedv-gui Tx as the reference Tx (e.g. |
I added a new option for TX feature capture:
Also, both
|
Interesting idea - but not quite what we need for the test use case I described. We want to feed an input wave file (instead of the mic input) to freedv-gui, and have it pass through the entire system. This might include a RF link instead of the audio cable. The Tx and Rx could be at separate sites (so no full duplex). The use of a fixed, constant input wave file allows us to repeat the test, for example changing RF drive levels or mic filtering in freedv-gui. It also tests almost all of the freedv-gui audio processing, so will trap any subtle bugs.
There may be some other tests we could perform with the -txfeaturefile feature (e.g. different mics), but the key to experiments is repeatability, and that will be hard to do with a new recording every time. Note: I edited the test use case example above, had .wav instead of .f32 for some of the files. |
The latest commit adds a
Then from the RADE repo:
Associated graphs below: Anyway, I'll double check the RADE transmit logic again as RX seemed okay per the above comments. |
I adjusted the scaling and that helped a tiny bit:
(0.343 instead of 0.350) I wonder if the sample rate adjustments made in the TX pipeline are messing things up, too. Based on my local config and the source code, it seems we go from 16 kHz (the input WAV file) -> 48 kHz -> 16 kHz (for feeding into the RADE TX), then 8 kHz -> 48 kHz for actually transmitting the signal. In theory it shouldn't, but you never know. We're also applying 4 dB additional attenuation to the RADE signal before TX to avoid users having to adjust the TX Attenuation dial when going back and forth between 700D/E/etc. and RADE, though I wouldn't think that'd mess anything up. The attenuation step is added as follows: auto txAttenuationStep = new LevelAdjustStep(outputSampleRate_, []() {
double dbLoss = g_txLevel / 10.0;
if (freedvInterface.getTxMode() == FREEDV_MODE_RADE)
{
// Attenuate by 4 dB as there's no BPF; anything louder distorts the signal
dbLoss -= 4.0;
}
double scaleFactor = exp(dbLoss/20.0 * log(10.0));
return scaleFactor;
});
pipeline_->appendPipelineStep(std::shared_ptr<IPipelineStep>(txAttenuationStep)); and scaling is basically: double scaleFactor = scaleFactorFn_();
for (int index = 0; index < numInputSamples; index++)
{
outputSamples[index] = inputSamples.get()[index] * scaleFactor;
} |
I tried
(for comparison, medium quality had a loss of 0.228) BTW I'm fairly sure it was SoX that was being used in the original FreeDV waveform: https://sourceforge.net/p/soxr/wiki/Home/. Is it worth investigating using that instead of |
Interesting!
|
This is just a brainstorm for future consideration (no need to start coding), but a neat way to tune over the air:
A very neat side effect of the ML work is we actually have a useful objective measure of speech quality. Never had that before. |
BTW I also tried setting the "analog" audio device sample rates to 16000 prior to running the tests and got the following:
which doesn't seem much different than the 0.205 above. I'd say resampling likely isn't much of a factor now. |
Yes I agree. A few thoughts:
|
@tmiw - I messed around with wav/mooneer.wav and it also has a higher loss compared to many other samples in wav. The sample sounds to me like it has some echo or reverb. On Audacity using select-all and Analyze-Plot Spectrum I can see a low pass response. Suggest you try a gamer style headset (wired) and see if that helps. I'm using:
To process, listen, measure and plot the loss. |
I don't have a headset immediately on me, but I did rerecord the file I used for previous tests with an XLR microphone and my Scarlett Solo USB interface. This seemed to turn out better: Loss figures:
(I can't currently test via loopback, unfortunately, but you can grab the file here (zipped due to GH not allowing direct uploads of .wav): FreeDV Voice Keyer - 16 kHz.wav.zip) |
Wow! That's a big drop in loss. The input sample sounds a lot nicer to me than wav/mooneer.wav - lots more high freq. That spectrum plot is similar in shape to several other samples in Another brainstorm: a tool/process for end users to test their microphone, e.g. record a sample, RADE enc/dec it (the modem wouldn't need to be in the path), print out a loss. BTW not suggesting we code this now, just 🤔 out loud...(maybe I should move this to an Issue). IIRC we have a similar metric from the 700D mic eq printed out on freedv-gui. One of the problems with general purpose Ham applications is the wide variety of input microphones, and custom filtering arrangements. Icom know what the freq response is of their microphone so can get consistent results. In the ML world - another way to handle this is train with a variety of spectral shaping. Other idea: we should be documenting this in a "RADE V1 user guide". e.g. use mics without reverb, check the loss |
I tried running the XLR sample through the RADE stack and the background noise on the input sample turns into an annoying frame rate buzzing 🤷 . Still much to learn about RADE tuning I guess. |
Hmm, I fixed the bug that was causing VHQ mode not to work (and HQ mode to apparently not work either on the M1 Mac Mini) and now loss in both resampling modes is a lot higher (there seemed to be no difference between VHQ and HQ). From the file I uploaded above:
The audio coming from freedv-gui still seems to sound okay so I'm not sure what's going on. It could be some sort of bug in how I'm capturing the RX features or maybe something else. Unfortunately my laptop (where I did the previous testing) had an unfortunate water-based incident so it has to wait until it comes back from Apple to confirm the results there. |
@tmiw - what was the engineering justification for the move to soxr? I'm concerned that we are running down a rabbit hole here based on an ad-hoc change. If you really want to run this resampler business to ground I can help you come up with some signal processing based tests to set appropriate "goal posts" for the work. |
soxr promises lower CPU usage and at least a little bit of an increase in audio quality. That said, a lot of the sampler related degregation did resolve itself when I increased quality to medium on libsamplerate. Anyway, I was able to get the ctests working but haven't been able to push the changes yet. The problem is that I'm still getting higher loss than expected but I don't know if it's something with the machine I'm using (I did previous testing on a x86 laptop, the more recent testing is on an ARM machine) or a bug that got introduced with a recent commit. I'll see if I can spend a bit more time chasing it down and if I don't get anywhere, I'll spin off the soxr changes into a separate PR and come back to them later. |
What evidence can you point me at to support the claim of increased quality? AFAIK there are no systematic tests of resamplers atm? CPU load in resamplers is not what we should be pursing atm - in fact the results above with low resolution libsrc re-samplers suggest optimisation it is something we should avoid until we really know what we are doing (ie tests that systematically test the resamplers and alert us of any subtle issues). We have been here before - premature and unwarranted optimisation will cause us problems. We need to focus on the lowest risk approach to a bug free freedv-gui signal processing path to support RADE. |
I was using the loss figures from
I checked out ce8c1ef (the final one before the introduction of soxr) and tried running the tests I've been doing again. On this machine at least, there didn't seem to be much difference in terms of the loss figure from |
if (freedvInterface.getTxMode() == FREEDV_MODE_RADE) | ||
{ | ||
// Attenuate by 4 dB as there's no BPF; anything louder distorts the signal | ||
dbLoss -= 4.0; | ||
} | ||
#endif // 0 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The level of the RADE signal should be set at the float to int conversion stage (correctly done above ☝️), not tweaked later in the Tx signal processing. This code should be rm-ed, not just if-deffed out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed in 2c3f6a2.
Per request from #770, this PR adds functionality to the current unit test framework to allow capture of the RX features from the RADE decoder.
Example usage:
Plot from above: